package com.gos.creator.web;

import com.gos.creator.domain.DataBase;
import com.gos.creator.service.DocumentCreatorService;
import com.gos.creator.service.MySqlCreatorService;
import com.gos.creator.service.MySqlMetaDataReader;
import com.gos.creator.service.impl.DocumentCreatorServiceImpl;
import com.gos.creator.service.impl.MySqlCreatorServiceImpl;
import com.gos.creator.service.impl.MySqlMetaDataReaderImpl;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.sql.Driver;
import java.util.HashMap;
import java.util.Map;

@Controller
public class IndexController {
    @PostMapping(path = "/gen")
    @ResponseBody
    public Object create(
            @RequestParam(name = "driver", required = false) String driver,
            @RequestParam(name = "url", required = false) String url,
            @RequestParam(name = "user", required = false) String user,
            @RequestParam(name = "password", required = false) String password,
            @RequestParam(name = "entity", required = false) String entity,
            @RequestParam(name = "dao", required = false) String dao,
            @RequestParam(name = "service", required = false) String service,
            @RequestParam(name = "directory", required = false) String directory) {
        final Map<String, Object> nr = new HashMap<>(16);
        Driver dri;
        try {
            final Class<?> driverImplementClass = Class.forName(driver);
            final Constructor<?> constructor = driverImplementClass.getDeclaredConstructor();
            dri = (Driver) constructor.newInstance();
        } catch (Exception ex) {
            final String stackTrace = toStackTrace(ex);
            nr.put("message", "注册数据库驱动不存在." + stackTrace);
            nr.put("status", "ERR");
            return nr;
        }
        if ((directory = directory.trim()).length() < 1) {
            nr.put("message", "请填写代码文件保存目录.");
            nr.put("status", "ERR");
            return nr;
        } else {
            File codeDirectory = new File(directory);
            if (!codeDirectory.exists()) {
                boolean success = codeDirectory.mkdirs();
                if (!success) {
                    nr.put("message", "代码文件保存目录:" + codeDirectory + "不存在,自动创建目录失败.");
                    nr.put("status", "ERR");
                    return nr;
                }
            }
        }
        if ((user = user.trim()).length() < 1) {
            nr.put("message", "请填写数据库用户名.");
            nr.put("status", "ERR");
            return nr;
        }
        if ((url = url.trim()).length() < 1) {
            nr.put("message", "请填写Url.");
            nr.put("status", "ERR");
            return nr;
        }
        if ((password = password.trim()).length() < 1) {
            nr.put("message", "请填写数据库密码.");
            nr.put("status", "ERR");
            return nr;
        }

        final MySqlMetaDataReader reader = new MySqlMetaDataReaderImpl();
        DataBase dataBase;
        try {
            dataBase = reader.read(dri, url, user, password);
        } catch (Exception e) {
            nr.put("message", "读取数据库失败." + e.getMessage());
            nr.put("status", "ERR");
            return nr;
        }
        MySqlCreatorService creatorService = new MySqlCreatorServiceImpl();

        try {
            creatorService.createEntities(dataBase, directory, entity);
            creatorService.createDao(dataBase, directory, entity, dao);
            creatorService.createService(dataBase, directory, entity, dao, service);
        } catch (Exception e) {
            try (Writer writer = new StringWriter(1024)) {
                e.printStackTrace(new PrintWriter(writer));
                nr.put("message", writer.toString());
                nr.put("status", "ERR");
            } catch (Exception ex) {

            }
            return nr;
        }
        nr.put("message", "生成成功...");
        nr.put("status", "OK");
        return nr;
    }


    @PostMapping(path = "/gen-doc")
    @ResponseBody
    public Object createDocument(@RequestParam(name = "driver", required = false) String driver,
                                 @RequestParam(name = "url", required = false) String url,
                                 @RequestParam(name = "user", required = false) String user,
                                 @RequestParam(name = "password", required = false) String password,
                                 @RequestParam(name = "directory", required = false) String directory) {
        final Map<String, Object> nr = new HashMap<>(16);
        Driver dri;
        try {
            final Class<?> driverImplementClass = Class.forName(driver);
            final Constructor<?> constructor = driverImplementClass.getDeclaredConstructor();
            dri = (Driver) constructor.newInstance();
        } catch (Exception ex) {
            final String stackTrace = toStackTrace(ex);
            nr.put("message", "注册数据库驱动不存在." + stackTrace);
            nr.put("status", "ERR");
            return nr;
        }
        if ((directory = directory.trim()).length() < 1) {
            nr.put("message", "请填写代码文件保存目录.");
            nr.put("status", "ERR");
            return nr;
        } else {
            File codeDirectory = new File(directory);
            if (!codeDirectory.exists()) {
                boolean success = codeDirectory.mkdirs();
                if (!success) {
                    nr.put("message", "代码文件保存目录:" + codeDirectory + "不存在,自动创建目录失败.");
                    nr.put("status", "ERR");
                    return nr;
                }
            }
        }
        if ((user = user.trim()).length() < 1) {
            nr.put("message", "请填写数据库用户名.");
            nr.put("status", "ERR");
            return nr;
        }
        if ((url = url.trim()).length() < 1) {
            nr.put("message", "请填写Url.");
            nr.put("status", "ERR");
            return nr;
        }
        if ((password = password.trim()).length() < 1) {
            nr.put("message", "请填写数据库密码.");
            nr.put("status", "ERR");
            return nr;
        }

        MySqlMetaDataReader reader = new MySqlMetaDataReaderImpl();
        DataBase dataBase;
        try {
            dataBase = reader.read(dri, url, user, password);
        } catch (Exception e) {
            nr.put("message", "读取数据库失败." + e.getMessage());
            nr.put("status", "ERR");
            return nr;
        }
        final DocumentCreatorService creatorService = new DocumentCreatorServiceImpl();
        boolean ok = creatorService.create(dataBase, directory);
        if (ok) {
            nr.put("status", "OK");
            nr.put("message", "生成成功...");
        } else {
            nr.put("status", "ERR");
            nr.put("message", "生成失败...");
        }
        return nr;
    }


    private static String toStackTrace(Exception e) {
        try (StringWriter writer = new StringWriter(1024)) {
            e.printStackTrace(new PrintWriter(writer));
            return writer.toString();
        } catch (Exception ex) {
            return null;
        }
    }

}


